
import ast
import re
from decimal import Decimal

from tools.handle_db import mysql
from tools.handle_ini import conf
from tools.handle_attribute import HandleAttribute
from tools.handle_phone import HandlePhone
from tools.handle_loging import my_logger,log_tojson

class HandleReplace:

    def __init__(self):
        self.handle_phone = HandlePhone()  # 手机号

    # 设置类属性(全局变量)
    def __set_attribute(self, key, val):
        setattr(HandleAttribute, key, val)

    # 通过脚本获取手机号（其他参数）
    def __get_phone_by_script(self, key):
        phone = self.handle_phone.get_phone()
        my_logger.info(msg="脚本生成未注册过的手机号:{}".format(phone))
        self.__set_attribute(key=key, val=phone)
        my_logger.info(msg="将脚本生成未注册过的手机号设置为类属性:{}={}".format(key,phone))

    # 从配置文件读取
    def __get_data_by_conf(self, key):
        data = conf.get(section=key, option=key)
        my_logger.info(msg="从配置文件读取到的参数:{}".format(data))
        self.__set_attribute(key=key, val=data)
        my_logger.info(msg="将配置文件读取到的参数设置为类属性:{}={}".format(key, data))

    # 从db里面获取数据
    def __get_data_by_db(self, key, sql):
        """
        [“member_phone”,"val"]
        :param key:
               type = list
        :param sql: sql语句
        :return: 无
        [{"mobile_hone":"1882099202020"}]
        """
        # 支持多个参数
        data = mysql.get_db_all_data(sql)
        my_logger.info(msg="从db中获取到的数据:{}".format(data))
        # self.__set_attribute(key=key, val=data[0][key])
        # my_logger.info(msg="将db中获取到的数据，并设置为类属性:{}={}".format(key,data[0][key]))


        for val in data[0].values():
            self.__set_attribute(key=key,val=val)
            my_logger.info(msg="将db中获取到的数据，并设置为类属性:{}={}".format(key, val))

    def __replace_data(self,data,key_list):
        """
        使用字符串replace方法替换请求参数
        :param data:
               :type=str
               excel中的请求参数
               {"mobile_phone":"#mobile_phone#","pwd":"Aa123456"}
        :param key_list:
               :type=list
               需要替换的key的list
               {"mobile_phone":["sql","select mobile_phone from  member where type=0 order by id desc limit 1"]}
        :return: str
        """
        my_logger.info(msg="==============开始参数替换==============")
        if isinstance(data,str):
            data = data
        else:
            data = str(data)
        my_logger.info(msg="替换之前的参数:\n{},类型为{}".format(log_tojson(data),type(data)))
        for key in key_list:
            data = data.replace(f"#{key}#",str(getattr(HandleAttribute,key)))
        my_logger.info(msg="==============参数替换结束==============")
        return data

    # 参数替换，对外访问，返回替换后的请求参数
    def replace_request_data(self, request_data, replace_request_data):
        """
        :param request_data:
                type = dict,str
                接口请求参数
        :param replace_request_data:
               type = str
               {"mobile_phone":["db","select mobile_phone from  member where type=0 order by id desc limit 1"]}
               {"mobile_phone":["conf"]}
               {"mobile_phone":["script"]}
               {"mobile_phone":["attribute"]}
        :return:
               :type=dict
        """
        try:
            my_logger.info(msg='参数替换传入请求参数：\n{}，类型为：{}'.format(log_tojson(request_data),type(request_data)))
            my_logger.info(msg='参数替换传入请求参数替换规则：\n{},类型为：{}'.format(log_tojson(replace_request_data),type(replace_request_data)))
            if request_data and replace_request_data:
                # 从参数替换规则中拿到需要替换参数的key
                replace_request_data = ast.literal_eval(replace_request_data)
                my_logger.info(msg="请求参数替换规则类型转换后\n{},类型为：{}".format(log_tojson(replace_request_data),type(replace_request_data)))
                replace_key_list = [key for key in replace_request_data.keys()]
                my_logger.info(msg="请求参数中需要替换的参数key列表\n{}".format(replace_request_data))
                for key,val in replace_request_data.items():
                    # (mobile_phone,[])
                    if val[0].lower() == "conf":
                        my_logger.info(msg="从conf配置文件获取需要替换的参数，并设置为类属性:{}".format(val[0]))
                        # 如果list中第一个标记位，为conf,就说明这个参数需要从配置文件去获取,取出来之后就设置为类属性
                        self.__get_data_by_conf(key=key)
                    elif val[0].lower() == "script":
                        if key == "mobile_phone": # 替换随机生成的手机号，未注册过的
                            my_logger.info(msg="脚本替换未注册过的手机号，并设置为类属性:{}".format(val[0]))
                            self.__get_phone_by_script(key=key)
                        else:
                            my_logger.info(msg="脚本替换只支持手机号，不支持该参数的脚本替换，参数替换时不做任何处理:{}".format(val[0]))
                    elif val[0].lower() == "attribute":
                        my_logger.info(msg="该参数已在类属性中，不需要再设置类属性，参数替换的时候可以直接拿:{}".format(val[0]))
                    elif val[0].lower() == "db":
                        if len(val) == 2:
                            my_logger.info(msg="从数据库获取需要替换的参数，并设置为类属性:{}".format(val[0]))
                            self.__get_data_by_db(key=key,sql=val[1])
                        else:
                            my_logger.info(msg="参数替换规则有误，没有写sql语句,传入的参数替换规则为:\n{}".format(log_tojson(replace_request_data)))
                    else:
                        my_logger.info(msg="不支持改替换场景，检查标记位,传入的参数替换规则为:\n{}".format(log_tojson(replace_request_data)))
                # 从这里开始做参数替换
                new_request_data_by_str = self.__replace_data(data=request_data, key_list=replace_key_list)
                my_logger.info(msg="替换后的请求参数为:\n{}，类型为{}".format(log_tojson(new_request_data_by_str),type(ast.literal_eval(new_request_data_by_str))))
                return ast.literal_eval(new_request_data_by_str)
            elif request_data and not replace_request_data:
                my_logger.info(msg="参数替换规则为空，不需要做参数替换,讲传入的请求参数转换成dict再返回:\n{},类型为:{}".format(log_tojson(request_data),type(ast.literal_eval(request_data))))
                return ast.literal_eval(request_data)
            else:
                my_logger.info(msg="请求参数和参数替换规则都为空，不需要替换参数，返回空字典")
                return {}
        except Exception as e:
            my_logger.exception(e)
            raise Exception("replace_request_data请求参数替换执行报错")

    def __get_sql_replace_keys(self,check_db):
        """
        正则获取需要替换的key,list
        :param check_db:
        :return:
               :type=list
               需要替换的字段list
               [mobile_phone1,mobile_phone2]
        """
        re_str = "#(\w.+?)#"
        key_list = re.findall(re_str,check_db)
        return key_list

    def replace_sql_data(self,check_db):
        """
        :param check_db:
               :type=str
               未替换的sql语句

        :return:
               :type=str
               替换后的完成sql语句
        """
        # select leave_amount from member where mobile_phone='#mobile_phone# and #mobile_phone2#
        # 1、获取需要替换的key

        key_list = self.__get_sql_replace_keys(check_db=check_db)
        if len(key_list)>0:
            new_check_db = self.__replace_data(data=check_db,key_list=key_list)
            return new_check_db
        else:
            return check_db

    def replace_check_db_data(self,check_db):
        """
          check_db={ "first": ["db", "select leave_amount from member where mobile_phone='#mobile_phone#'"],
            "second": ["none",18820991515]}
        :param check_db:
        check_db={ "first": "select leave_amount from member where mobile_phone='18820992515',
            "second":"select leave_amount from member where mobile_phone='18820992515'"}
        :return:
        """
        if isinstance(check_db,dict):
            check_db = check_db
        else:
            check_db = ast.literal_eval(check_db)
        # 遍历 check_db中的数据
        for key in  check_db.keys():
            tag = check_db[key][0]
            # 替换sql语句
            if tag.upper() == "DB":
                # 替换sql语句中的参数
                replace_sql = self.replace_sql_data(check_db=check_db[key][1])
                #check_db[key][1] 去替换
                # 去替换sql语句中需要替换的字段,返回替换后的sql（完整的sql语句）
                # sql_vaule= {amount:decimal(1234)}
                sql_value = mysql.get_db_all_data(sql=replace_sql)[0]
                val = list(sql_value.values())[0]
                if isinstance(val,Decimal):
                    val = float(val)
                else:
                    pass
                check_db[key] = val
            # 如果标记位为none，表示数据写死，后面必须跟一个写死的值，直接获取最后的值进行替换
            elif tag.upper() == "NONE":
                check_db[key] = check_db[key][1]
            else:
                check_db[key] = getattr(HandleAttribute,check_db[key][0])
        return check_db